
/**
 * @copyright Copyright (c) 2025 
 * CSG Digital Grid Technology (Guangdong) Co., Ltd.
 * @author xxxcsg
 * @brief 启动辅助工具程序，用于操作 misc 分区的 bootloader 相关配置
 * @details 支持设置系统启动槽位（a/b）、标记运行中槽位、设置启动命令/系统状态、
 *          读取 misc 分区信息及清空 misc 分区等功能，通过命令行参数触发对应操作
 */
#include <stdio.h>
#include "include/misc_inf.h"

#define MISC    "/dev/block/mmcblk0p3"
#define BINARY_MAX_ARGS     3
#define WRITE_SECOND_CMD    2
#define CMDLINE_BUF	2048

int get_root() {
	
	int ret;
	ssize_t bytes;
	ssize_t total = 0;
	char cmdline[CMDLINE_BUF] = {};
    char which;
	
    int fd = open("/proc/cmdline", O_RDONLY);
    if (fd < 0) {
        printf("cmdline open failed : %s\n", strerror(errno));
        return -1;
    }
	
	while((bytes = read(fd, cmdline, sizeof(cmdline) -1)) >0) {
		total = total + bytes;
	}

	cmdline[total] = '\0';
	
	if(strstr(cmdline, "mmcblk0p6")) {  //3403
	//if(strstr(cmdline, "mmcblk0p7")){   //3519
          which = 'a';
        } else {
	  which = 'b';
	}

	ret = close(fd);
    if (ret != 0) {
        printf("cmdline close failed : %s\n", strerror(errno));
        return -1;
    }

    return (which == 'a') ? 0 : 1;
}


static void print_usage() {
    printf("Usage: boot_helper <sub-command> <value>\n");
    printf("Boot_helper helps user to set bootloader message.\nSub-command:\n");
    printf("setslot <a|b>         Set from which slot to boot system\n");
    printf("setrunning            Set the slot on which system is running\n");
    printf("setcommand <string>   Set boot command for bootloader\n");
    printf("setstatus <string>    Set system status for bootloader\n");
    printf("getinfo               Get bootloader infor from misc partition\n");
    printf("clear                 Clear misc partition\n");
}

int main(int argc, char **argv) {

    int ret;

    if (argc == 1) {
        print_usage();
        return -1;
    }

    boot_msg boot;
    memset(&boot, 0x00, sizeof(boot_msg));
    ret = read_boot_msg(MISC, &boot);
    if (ret != 0) {
        printf("read_boot_msg failed!\n" );
        return -1;
    }

    if (strcmp(argv[1], "setslot") == 0) {
        if (argc < BINARY_MAX_ARGS) {
            print_usage();
            return -1;
        }

        if (argv[WRITE_SECOND_CMD] != NULL) {
            if ((strcmp(argv[WRITE_SECOND_CMD], "a") == 0)) {
                boot.slot[0] = 'a';
            } else if ((strcmp(argv[WRITE_SECOND_CMD], "b") == 0))
            {
                boot.slot[0] = 'b';
            } else {
                print_usage();
                return -1;
            }
        }

        ret = write_boot_msg(MISC, &boot);
        if (ret != 0) {
            printf("write_boot_msg failed!\n" );
            return -1;
        }

        printf("write_boot_msg successful.\n");

     } else if (strcmp(argv[1], "setrunning") == 0) {
        if (argc >= BINARY_MAX_ARGS) {
            print_usage();
            return -1;
        }

        if (get_root() == 0) {
            boot.running_slot[0] = 'a';
        } else {
            boot.running_slot[0] = 'b';
        }

        ret = write_boot_msg(MISC, &boot);
        if (ret != 0) {
            printf("write_boot_msg failed!\n" );
            return -1;
        }

        printf("write_boot_msg successful.\n");

    } else if (strcmp(argv[1], "setcommand") == 0) {
        if (argc < BINARY_MAX_ARGS) {
            print_usage();
            return -1;
        }

        if (argv[WRITE_SECOND_CMD] != NULL) {
            memset(boot.command, 0x00, sizeof(boot.command));
            if (snprintf_s(boot.command, sizeof(boot.command), sizeof(boot.command) - 1, "%s", argv[WRITE_SECOND_CMD]) == -1) {
                printf("write_boot_msg snprintf_s failed!\n");
                return -1;
            }
        }

        ret = write_boot_msg(MISC, &boot);
        if (ret != 0) {
            printf("write_boot_msg failed!\n" );
            return -1;
        }

        printf("write_boot_msg successful.\n");

    } else if (strcmp(argv[1], "setstatus") == 0) {
        if (argc < BINARY_MAX_ARGS) {
            print_usage();
            return -1;
        }

        if (argv[WRITE_SECOND_CMD] != NULL) {
            memset(boot.status, 0x00, sizeof(boot.status));
            if (snprintf_s(boot.status, sizeof(boot.status), sizeof(boot.status) - 1, "%s", argv[WRITE_SECOND_CMD]) == -1) {
                printf("write_boot_msg snprintf_s failed!\n");
                return -1;
            }
        }
        
        ret = write_boot_msg(MISC, &boot);
        if (ret != 0) {
            printf("write_boot_msg failed!\n" );
            return -1;
        }

        printf("write_boot_msg successful.\n");

    } else if (strcmp(argv[1], "getinfo") == 0) {
        ret = read_boot_msg(MISC, &boot);
        if (ret != 0) {
            printf("read_boot_msg failed!\n" );
            return -1;
        }

        print_misc_data(&boot);
        printf("read_boot_msg successful.\n");

    } else if (strcmp(argv[1], "clear") == 0) {
        boot_msg data;
        memset(&data, 0x00, sizeof(boot_msg));

        ret = write_boot_msg(MISC, &data);
        if (ret != 0) {
            printf("write_boot_msg failed!\n" );
            return -1;
        }

        printf("clear misc done.\n" );

    } else {
        print_usage();
        return -1;
    }

    return 0;
}
